package com.xiaoshuidi.cloud.module.bpm.service.reserveapartmentconfig;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.module.bpm.api.reserveapartmentconfig.vo.CreateReserveApartmentConfigReqVO;
import com.xiaoshuidi.cloud.module.bpm.controller.admin.reserveapartmentconfig.vo.ReserveApartmentConfigPageReqVO;
import com.xiaoshuidi.cloud.module.bpm.controller.admin.reserveapartmentconfig.vo.ReserveApartmentConfigPageRespVO;
import com.xiaoshuidi.cloud.module.bpm.controller.admin.reserveapartmentconfig.vo.SetupReserveNumReqVO;
import com.xiaoshuidi.cloud.module.bpm.dal.dataobject.reserveapartmentconfig.ReserveApartmentConfig;
import com.xiaoshuidi.cloud.module.bpm.dal.mysql.reserveapartmentconfig.ReserveApartmentConfigMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.module.system.api.user.AdminUserApi;
import com.xiaoshuidi.cloud.module.system.api.user.dto.AdminUserRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 门店预约配置 服务实现类
 * </p>
 *
 * @author hans.zhang
 * @since 2023-12-01
 */
@Service
@RequiredArgsConstructor
public class ReserveApartmentConfigServiceImpl extends ServiceImpl<ReserveApartmentConfigMapper, ReserveApartmentConfig> implements ReserveApartmentConfigService {

    private final ReserveApartmentConfigMapper reserveApartmentConfigMapper;
    private final AdminUserApi adminUserApi;

    @Override
    public CommonResult<PageResult<ReserveApartmentConfigPageRespVO>> getPage(ReserveApartmentConfigPageReqVO reqVO) {
        LambdaQueryWrapper<ReserveApartmentConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.select(ReserveApartmentConfig::getApartmentId);
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getApartmentId()), ReserveApartmentConfig::getApartmentId, reqVO.getApartmentId());
        wrapper.groupBy(ReserveApartmentConfig::getApartmentId);
        Page<ReserveApartmentConfig> reserveApartmentConfigPage = reserveApartmentConfigMapper.selectPage(new Page<>(reqVO.getPageNo(), reqVO.getPageSize()), wrapper);
        List<ReserveApartmentConfig> records = reserveApartmentConfigPage.getRecords();
        List<Long> apartmentIds = records.stream().map(ReserveApartmentConfig::getApartmentId).collect(Collectors.toList());
        Map<Long, List<ReserveApartmentConfig>> map = new HashMap<>();
        HashSet<Long> sets = new HashSet<>();
        if(ObjectUtil.isNotEmpty(apartmentIds)){
            wrapper = Wrappers.lambdaQuery();
            wrapper.in(ReserveApartmentConfig::getApartmentId, apartmentIds);
            List<ReserveApartmentConfig> reserveApartmentConfigs = reserveApartmentConfigMapper.selectList(wrapper);
            Set<Long> collect = reserveApartmentConfigs.stream().filter(p -> ObjectUtil.isNotEmpty(p.getUpdater())).map(p -> {
                return Long.valueOf(p.getUpdater());
            }).collect(Collectors.toSet());
            sets.addAll(collect);
            map = reserveApartmentConfigs.stream().collect(Collectors.groupingBy(ReserveApartmentConfig::getApartmentId));
        }
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(sets);
        List<ReserveApartmentConfigPageRespVO> respVOS = new ArrayList<>();
        for (ReserveApartmentConfig record : records) {
            List<ReserveApartmentConfig> reserveApartmentConfigs = map.get(record.getApartmentId());
            ReserveApartmentConfig apartmentConfig = reserveApartmentConfigs.get(0);
            ReserveApartmentConfigPageRespVO respVO = new ReserveApartmentConfigPageRespVO();
            respVO.setId(apartmentConfig.getId());
            respVO.setApartmentId(apartmentConfig.getApartmentId());
            respVO.setApartmentName(apartmentConfig.getApartmentName());
            Map<Integer, List<ReserveApartmentConfig>> collect = reserveApartmentConfigs.stream().collect(Collectors.groupingBy(ReserveApartmentConfig::getTimePeriod));
            respVO.setTimePeriodNum1(collect.get(1).get(0).getNum());
            respVO.setTimePeriodNum2(collect.get(2).get(0).getNum());
            respVO.setTimePeriodNum3(collect.get(3).get(0).getNum());
            respVO.setTimePeriodNum4(collect.get(4).get(0).getNum());
            respVO.setTimePeriodNum5(collect.get(5).get(0).getNum());
            respVO.setTimePeriodNum6(collect.get(6).get(0).getNum());
            respVO.setUpdateTime(apartmentConfig.getUpdateTime());
            if(ObjectUtil.isNotEmpty(apartmentConfig.getUpdater())){
                AdminUserRespDTO adminUserRespDTO = userMap.get(Long.valueOf(apartmentConfig.getUpdater()));
                respVO.setUpdaterName(ObjectUtil.isEmpty(adminUserRespDTO) ? "" : adminUserRespDTO.getNickname());
            }
            respVOS.add(respVO);
        }
        return CommonResult.success(new PageResult<>(respVOS, reserveApartmentConfigPage.getTotal()));
    }

    /**
     * 设置预约人数
     * @param reqVO
     * @return
     */
    @Override
    public CommonResult<Boolean> setupReserveNum(SetupReserveNumReqVO reqVO) {
        LambdaQueryWrapper<ReserveApartmentConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ReserveApartmentConfig::getApartmentId, reqVO.getApartmentId());
        List<ReserveApartmentConfig> reserveApartmentConfigs = reserveApartmentConfigMapper.selectList(wrapper);
        Map<Integer, Integer> timePeriodAndNum = reqVO.getTimePeriodAndNum();
        for (ReserveApartmentConfig reserveApartmentConfig : reserveApartmentConfigs) {
            LambdaUpdateWrapper<ReserveApartmentConfig> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(ReserveApartmentConfig::getId, reserveApartmentConfig.getId());
            updateWrapper.set(ReserveApartmentConfig::getNum,timePeriodAndNum.get(reserveApartmentConfig.getTimePeriod()));
            updateWrapper.set(ReserveApartmentConfig::getUpdateTime,LocalDateTime.now());
            reserveApartmentConfigMapper.update(null, updateWrapper);
        }
        // this.updateBatchById(reserveApartmentConfigs);
        return CommonResult.success(Boolean.TRUE);
    }

    /**
     * 根据门店id和时间段获取配置信息
     * @param apartmentId 门店id
     * @param timePeriod 时间段
     * @return
     */
    @Override
    public ReserveApartmentConfig getByApartmentIdAndTimePeriod(Long apartmentId, Integer timePeriod) {
        LambdaQueryWrapper<ReserveApartmentConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ReserveApartmentConfig::getApartmentId, apartmentId);
        wrapper.eq(ReserveApartmentConfig::getTimePeriod, timePeriod);
        wrapper.last("limit 1");
        return reserveApartmentConfigMapper.selectOne(wrapper);
    }

    @Override
    public List<ReserveApartmentConfig> getByApartmentId(Long apartmentId) {
        LambdaQueryWrapper<ReserveApartmentConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ReserveApartmentConfig::getApartmentId, apartmentId);
        return reserveApartmentConfigMapper.selectList(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createReserveApartmentConfig(CreateReserveApartmentConfigReqVO reqVO) {
        // 检查是否已经存在配置, 已存在的话,不需要重复添加
        LambdaQueryWrapper<ReserveApartmentConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ReserveApartmentConfig::getApartmentId, reqVO.getApartmentId());
        List<ReserveApartmentConfig> configs = this.list(wrapper);
        if(ObjectUtil.isNotEmpty(configs)){
            return Boolean.TRUE;
        }
        List<ReserveApartmentConfig> reserveApartmentConfigs = new ArrayList<>();
        for (int i = 1; i < 7; i++) {
            ReserveApartmentConfig reserveApartmentConfig = new ReserveApartmentConfig();
            reserveApartmentConfig.setApartmentId(reqVO.getApartmentId());
            reserveApartmentConfig.setApartmentName(reqVO.getApartmentName());
            reserveApartmentConfig.setDeptId(reqVO.getDeptId());
            reserveApartmentConfig.setTimePeriod(i);
            reserveApartmentConfigs.add(reserveApartmentConfig);
        }
        this.saveBatch(reserveApartmentConfigs);
        return Boolean.TRUE;
    }

    /**
     * 预约人数回显
     * @param apartmentId
     * @return
     */
    @Override
    public Map<Integer, Integer> getReserveNum(Long apartmentId) {
        LambdaQueryWrapper<ReserveApartmentConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ReserveApartmentConfig::getApartmentId, apartmentId);
        wrapper.orderByAsc(ReserveApartmentConfig::getTimePeriod);
        List<ReserveApartmentConfig> reserveApartmentConfigs = reserveApartmentConfigMapper.selectList(wrapper);
        HashMap<Integer, Integer> map = new HashMap<>();
        for (ReserveApartmentConfig reserveApartmentConfig : reserveApartmentConfigs) {
            map.put(reserveApartmentConfig.getTimePeriod(), reserveApartmentConfig.getNum());
        }
        return map;
    }

}
